package containerlogistik.implementation;

import static containerlogistik.implementation.Values.*;
import containerlogistik.interfaces.Point;

public class PointIn2d extends AbstractValue<Point> implements Point {

    private final int x;
    private final int y;

    private PointIn2d(int x, int y) {
        this.x = x;
        this.y = y;
    }

    static PointIn2d valueOf(int x, int y) {
        return new PointIn2d(x, y);
    }

    @Override
    public int x() {
        return this.x;
    }

    @Override
    public int y() {
        return this.y;
    }

    @Override
    public int compareTo(Point o) {
        int tmp = Integer.compare(this.x(), o.x());
        return (tmp != 0 ? tmp : Integer.compare(this.y(), o.y()));
    }

    @Override
    public String toString() {
        return String.format("PointIn2d{x=%s, y=%s}",
                this.x(), this.y());
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Point)) {
            return false;
        }
        return this.compareTo((Point) obj) == 0;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 41 * hash + this.x;
        return hash;
    }

    @Override
    public Point add(Point value) {
        return pointIn2d(this.x() + value.x(), this.y() + value.y());
    }

    @Override
    public Point addOnX(int x) {
        return pointIn2d(this.x() + x, this.y());
    }

    @Override
    public Point addOnY(int y) {
        return pointIn2d(this.x(), this.y() + y);
    }

    @Override
    public Point addOnX(double x) {
        return this.addOnX(new Double(DoubleUtils.round(x, 0)).intValue());
    }

    @Override
    public Point addOnY(double y) {
        return this.addOnY(new Double(DoubleUtils.round(y, 0)).intValue());
    }

    @Override
    public Point sub(Point value) {
        return pointIn2d(this.x() - value.x(), this.y() - value.y());
    }

    @Override
    public Point subOnX(int x) {
        return pointIn2d(this.x() - x, this.y());
    }

    @Override
    public Point subOnY(int y) {
        return pointIn2d(this.x(), this.y() - y);
    }

    @Override
    public Point subOnX(double x) {
        return this.subOnX(new Double(DoubleUtils.round(x, 0)).intValue());
    }

    @Override
    public Point subOnY(double y) {
        return this.subOnY(new Double(DoubleUtils.round(y, 0)).intValue());
    }

    @Override
    public Point mul(Point value) {
        return pointIn2d(this.x() * value.x(), this.y() * value.y());
    }

    @Override
    public Point mulOnX(int x) {
        return pointIn2d(this.x() * x, this.y());
    }

    @Override
    public Point mulOnY(int y) {
        return pointIn2d(this.x(), this.y() * y);
    }

    @Override
    public Point mulOnX(double x) {
        return this.mulOnX(new Double(DoubleUtils.round(x, 0)).intValue());
    }

    @Override
    public Point mulOnY(double y) {
        return this.mulOnY(new Double(DoubleUtils.round(y, 0)).intValue());
    }
    
    
}
